package org.example.hotel.service;

import org.example.hotel.dto.BillingDTO;
import org.example.hotel.dto.BillingDetailDTO;
import org.example.hotel.entity.CheckinRecord;
import org.example.hotel.entity.Room;
import org.example.hotel.entity.UsageRecord;
import org.example.hotel.repository.CheckinRecordRepository;
import org.example.hotel.repository.RoomRepository;
import org.example.hotel.repository.UsageRecordRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class BillingService {

    @Autowired
    private RoomRepository roomRepository;

    @Autowired
    private CheckinRecordRepository checkinRecordRepository;

    @Autowired
    private UsageRecordRepository usageRecordRepository;

    @Autowired
    private ScheduleService scheduleService;

    public BillingDTO getBilling(int roomId) {
        // 找当前房间活跃的入住记录（未退房）
        CheckinRecord checkinRecord = checkinRecordRepository.findByRoomIdAndCheckoutTimeIsNull(roomId)
                .orElseThrow(() -> new RuntimeException("该房间无正在入住的记录"));

        LocalDateTime checkIn = checkinRecord.getCheckinTime();
        LocalDateTime checkOut = (checkinRecord.getCheckoutTime() != null) ? checkinRecord.getCheckoutTime() : LocalDateTime.now();

        // 直接从入住记录读取房费，不用再计算
        double stayCost = checkinRecord.getRoomCost();

        // 计算空调费用，只计算入住-退房时间内的
        double acCost = usageRecordRepository.findByRoomId(roomId).stream()
                .filter(r -> !r.getStartTime().isBefore(checkIn) && !r.getEndTime().isAfter(checkOut))
                .mapToDouble(UsageRecord::getCost)
                .sum();

        return new BillingDTO(
                roomId,
                checkIn.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
                checkOut.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
                stayCost,
                acCost,
                stayCost + acCost
        );
    }

    public BillingDetailDTO getBillingDetail(int roomId) {
        // 获取当前入住记录
        CheckinRecord checkinRecord = checkinRecordRepository.findByRoomIdAndCheckoutTimeIsNull(roomId)
                .orElseThrow(() -> new RuntimeException("该房间无正在入住的记录"));

        LocalDateTime checkIn = checkinRecord.getCheckinTime();
        LocalDateTime checkOut = (checkinRecord.getCheckoutTime() != null) ? checkinRecord.getCheckoutTime() : LocalDateTime.now();

        // 过滤时间范围内的空调使用记录
        List<UsageRecord> records = usageRecordRepository.findByRoomId(roomId).stream()
                .filter(r -> !r.getStartTime().isBefore(checkIn) && !r.getEndTime().isAfter(checkOut))
                .toList();

        AtomicInteger lowTime = new AtomicInteger(0), medTime = new AtomicInteger(0), highTime = new AtomicInteger(0);
        double[] lowCost = {0}, medCost = {0}, highCost = {0};

        List<String> lowPeriods = records.stream()
                .filter(r -> "LOW".equalsIgnoreCase(r.getFanSpeed()))
                .peek(r -> {
                    lowTime.addAndGet((int) r.getDuration());
                    lowCost[0] += r.getCost();
                })
                .map(UsageRecord::getTimePeriod)
                .collect(Collectors.toList());

        List<String> medPeriods = records.stream()
                .filter(r -> "MEDIUM".equalsIgnoreCase(r.getFanSpeed()))
                .peek(r -> {
                    medTime.addAndGet((int) r.getDuration());
                    medCost[0] += r.getCost();
                })
                .map(UsageRecord::getTimePeriod)
                .collect(Collectors.toList());

        List<String> highPeriods = records.stream()
                .filter(r -> "HIGH".equalsIgnoreCase(r.getFanSpeed()))
                .peek(r -> {
                    highTime.addAndGet((int) r.getDuration());
                    highCost[0] += r.getCost();
                })
                .map(UsageRecord::getTimePeriod)
                .collect(Collectors.toList());

        return new BillingDetailDTO(
                roomId,
                lowTime.get(), medTime.get(), highTime.get(),
                lowPeriods, medPeriods, highPeriods,
                lowCost[0], medCost[0], highCost[0],
                lowCost[0] + medCost[0] + highCost[0]
        );
    }


    public BillingDTO checkOut(int roomId) {
        // 找当前活跃入住记录
        CheckinRecord checkinRecord = checkinRecordRepository.findByRoomIdAndCheckoutTimeIsNull(roomId)
                .orElseThrow(() -> new RuntimeException("该房间无正在入住的记录"));

        // 先调用getBilling读取账单
        BillingDTO billing = getBilling(roomId);

        // 设定退房时间
        checkinRecord.setCheckoutTime(LocalDateTime.now());
        checkinRecordRepository.save(checkinRecord);

        // 释放房间资源，更新房间状态
        scheduleService.releaseRoom(roomId);

        Room room = roomRepository.findById(roomId).orElseThrow(() -> new RuntimeException("房间不存在"));
        room.setOccupied(false);
        roomRepository.save(room);

        return billing;
    }
}
